Test a crate that is both a plugin and a proc macro
authorDavid Tolnay <dtolnay@gmail.com>
Thu, 1 Sep 2016 17:42:23 +0000 (10:42 -0700)
committerDavid Tolnay <dtolnay@gmail.com>
Thu, 1 Sep 2016 17:42:23 +0000 (10:42 -0700)
src/cargo/util/toml.rs
tests/rustc-macro.rs

index 811e58b49c4ba75d97040179aadaa1888c555f24..15e5246315d711265063752c1bb32d6f772064df 100644 (file)
@@ -1011,6 +1011,15 @@ impl TomlTarget {
     }
 
     fn validate_crate_type(&self) -> CargoResult<()> {
+        // Per the Macros 1.1 RFC:
+        //
+        // > Initially if a crate is compiled with the rustc-macro crate type
+        // > (and possibly others) it will forbid exporting any items in the
+        // > crate other than those functions tagged #[rustc_macro_derive] and
+        // > those functions must also be placed at the crate root.
+        //
+        // A plugin requires exporting plugin_registrar so a crate cannot be
+        // both at once.
         if self.plugin == Some(true) && self.rustc_macro == Some(true) {
             Err(human("lib.plugin and lib.rustc-macro cannot both be true".to_string()))
         } else {
index fe49b359d2dbe61f053bd1565a588469488958c7..f3d618b1228e62922581d053abbf62e9a26b9a04 100644 (file)
@@ -144,3 +144,44 @@ fn impl_and_derive() {
     assert_that(client.cargo("run"),
                 execs().with_status(0).with_stdout("X { success: true }"));
 }
+
+#[test]
+fn plugin_and_rustc_macro() {
+    if !is_nightly() {
+        return;
+    }
+
+    let questionable = project("questionable")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "questionable"
+            version = "0.0.1"
+            authors = []
+
+            [lib]
+            plugin = true
+            rustc-macro = true
+        "#)
+        .file("src/lib.rs", r#"
+            #![feature(plugin_registrar, rustc_private)]
+            #![feature(rustc_macro, rustc_macro_lib)]
+
+            extern crate rustc_plugin;
+            use rustc_plugin::Registry;
+
+            extern crate rustc_macro;
+            use rustc_macro::TokenStream;
+
+            #[plugin_registrar]
+            pub fn plugin_registrar(reg: &mut Registry) {}
+
+            #[rustc_macro_derive(Questionable)]
+            pub fn questionable(input: TokenStream) -> TokenStream {
+                input
+            }
+        "#);
+
+    let msg = "  lib.plugin and lib.rustc-macro cannot both be true";
+    assert_that(questionable.cargo_process("build"),
+                execs().with_status(101).with_stderr_contains(msg));
+}